package com.mk.utils;

import com.mk.properties.JwtProperties;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import io.jsonwebtoken.io.Decoders;
import io.jsonwebtoken.security.Keys;
import org.springframework.stereotype.Component;

import javax.crypto.SecretKey;
import java.security.Key;
import java.util.Date;
import java.util.function.Function;

/**
 * JWT工具类
 * @since 2025-05-14 15:07
 */
@Component
public class JwtUtil {

    // 密钥
    private final SecretKey secretKey;
    private final JwtProperties jwtProperties;

    // 默认过期时间：3小时
    private static final long EXPIRATION_TIME = 10800000L;

    // JWT 签名算法
    private static final SignatureAlgorithm SIGNATURE_ALGORITHM = SignatureAlgorithm.HS256;

//    // 构造函数，使用指定的密钥
//    public JwtUtil(String secret) {
//        this.secretKey = Keys.hmacShaKeyFor(secret.getBytes());
//    }

//    // 构造函数，使用自动生成的安全密钥
//    public JwtUtil() {
//        this.secretKey = Keys.secretKeyFor(SIGNATURE_ALGORITHM);
//    }

    // 通过构造函数注入 JwtProperties
    public JwtUtil(JwtProperties jwtProperties) {
        this.jwtProperties = jwtProperties;
        // 在构造函数中初始化密钥
        //byte[] keyBytes = Decoders.BASE64.decode(jwtProperties.getUserSecretKey());
        this.secretKey = Keys.hmacShaKeyFor(jwtProperties.getSecretKey().getBytes());
    }


    // 生成 JWT Token
    public String generateToken(String username) {
        return generateToken(username, EXPIRATION_TIME);
    }

    // 生成 JWT Token，支持自定义过期时间
    public String generateToken(String username, long expirationTime) {
        return Jwts.builder()
                .setSubject(username)
                .setIssuedAt(new Date())
                .setExpiration(new Date(System.currentTimeMillis() + expirationTime))
                .signWith(secretKey, SIGNATURE_ALGORITHM)
                .compact();
    }

    // 从 Token 中提取用户名（可以通过Token中的"sub"字段获取）
    public String extractUsername(String token) {
        return extractClaim(token, Claims::getSubject);
    }

    // 从 Token 中提取特定声明（比如用户名、角色等）
    public <T> T extractClaim(String token, Function<Claims, T> claimsResolver) {
        // 提取所有声明
        final Claims claims = extractAllClaims(token);
        return claimsResolver.apply(claims);
    }

    // 从 Token 中提取所有声明
    private Claims extractAllClaims(String token) {
        return Jwts.parserBuilder()
                // 设置签名密钥
                .setSigningKey(secretKey)
                .build()
                .parseClaimsJws(token)
                .getBody();
    }

    // 校验 Token 是否有效
    public boolean isTokenExpired(String token) {
        // 判断过期时间是否小于当前时间
        return extractExpiration(token).before(new Date());
    }

    // 提取 Token 的过期时间
    public Date extractExpiration(String token) {
        return extractClaim(token, Claims::getExpiration);
    }

    // 校验 Token 是否有效（验证过期和签名）
    public boolean validateToken(String token, String username) {
        return (username.equals(extractUsername(token)) && !isTokenExpired(token));
    }

    // 刷新 Token（生成新的 Token）
    public String refreshToken(String token) {
        final String username = extractUsername(token);
        // 重新生成新的 Token
        return generateToken(username);
    }
}
